package com.glc.hms.system.job.SessionJob;

import com.glc.hms.config.ShiroConfig;
import com.glc.hms.core.shiro.SingletonSessionManager;
import com.glc.hms.holder.ShiroSessionHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Deque;
import java.util.Iterator;
import java.util.Map;

/**
 * author Santa
 * Date 2019/12/11
 */
@Slf4j
@Component
@Configuration      //1.主要用于标记配置类，兼备Component的效果。
@EnableScheduling
public class SessionValidate {

    private Integer maxSession = ShiroConfig.getMaxSession();
    private Boolean kickoutAfter = ShiroConfig.getKickoutAfter();

    private DefaultWebSessionManager sessionManager = SingletonSessionManager.getInstance();

    @Scheduled(fixedRate = 10000)
    public void sessionValidate(){
        Map<Long, Deque<Serializable>> sessions = ShiroSessionHolder.getSessionCache();
        if (sessions != null) {
            int i = 0;
            for (Long userId : sessions.keySet()) {
                Deque<Serializable> deque = sessions.get(userId);
                if(deque.size()>0){
                while (deque.size()>maxSession){
                    Serializable serializable;
                    if(kickoutAfter) {
                        //从队列移除  并把session销毁
                        serializable  = deque.removeFirst();
                    } else { //否则踢出前者
                        serializable = deque.removeLast();
                    }
                    Session session = null;
                    try {
                        session = sessionManager.getSession(new DefaultSessionKey(serializable));
                        session.stop();
                    } catch (SessionException e) {
                        log.info("this session has expire");
                    }
                    log.info("remove session:"+serializable);
                }

                Iterator<Serializable> iterator = deque.iterator();
                while(iterator.hasNext()){
                    Serializable next = iterator.next();
                    try {
                        sessionManager.getSession(new DefaultSessionKey(next));
                        i++;
                    } catch (SessionException e) {
                        log.info("remove expire session:"+next);
                        iterator.remove();
                    }
                }
            }else {
                    sessions.remove(userId);
                }
            }
        }
    }

    public static Integer getOnLineUser(){
        return ShiroSessionHolder.getSessionCacheList().size();
    }
}























